package com.jdd.config.websocket;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jdd.common.constant.JddConstant;
import com.jdd.modules.parking.entity.ParkWorkStation;
import com.jdd.modules.parking.mapper.ParkWorkStationMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * WebSocketServer
 */

@ServerEndpoint("/websocket/{clientId}")
@Component
@Slf4j
public class WebSocketServer {
    private static ParkWorkStationMapper parkWorkStationMapper;

    @Resource
    private void setParkWorkStationMapper(ParkWorkStationMapper parkWorkStationMapper) {
        WebSocketServer.parkWorkStationMapper = parkWorkStationMapper;
    }

    /**
     * 静态变量，用来记录当前在线连接数
     */
    private static int onlineCount = 0;
    /**
     * 存放每个客户端对应的MyWebSocket对象。
     */
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;
    /**
     * 接收clientId
     */
    private String clientId = "";


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("clientId") String clientId) {
        this.session = session;
        this.clientId = clientId;
        if (webSocketMap.containsKey(clientId)) {
            webSocketMap.remove(clientId);
            webSocketMap.put(clientId, this);
            //加入set中
        } else {
            webSocketMap.put(clientId, this);
            //加入set中
            addOnlineCount();
            //在线数加1
        }

        log.info("连接:" + clientId + ",当前在线客户端为:" + getOnlineCount());

        try {
            sendMessage("连接成功");
            //设置上线
            updateStatus(clientId,JddConstant.StringNumber.STRING_ONE);
        } catch (IOException e) {
            log.error("客户端:" + clientId + ",网络异常!!!!!!");
        }
    }



    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("clientId") String clientId) {
        if (webSocketMap.containsKey(clientId)) {
            webSocketMap.remove(clientId);
            //从set中删除
            subOnlineCount();
        }
        //设置离线
        updateStatus(clientId,JddConstant.StringNumber.STRING_ZERO);
        log.info("客户端退出:" + clientId + ",当前在线客户端为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("客户消息:" + clientId + ",报文:" + message);
        //可以群发消息
        //消息保存到数据库、redis
        if (StringUtils.isNotBlank(message)) {
            try {
                //解析发送的报文
                Map<String, Boolean> json = new HashMap<>(8);
                json.put("isConnect", true);
                String str = JSON.toJSONString(json);
                //追加发送人(防止串改)
                sendInfo(str, clientId);

                QueryWrapper<ParkWorkStation> wrapper = new QueryWrapper<>();
                wrapper.eq("used_user_id", clientId).orderByDesc("create_time");
                List<ParkWorkStation> list = parkWorkStationMapper.selectList(wrapper);
                if (ObjectUtil.isEmpty(list)) {
                    log.error("当前used_user_id无对应工作站！");
                    return;
                }
                parkWorkStationMapper.updateUpdateTimeById(list.get(0).getId());
//                jsonObject.put("fromclientId", this.clientId);
//                String toclientId = jsonObject.getString("toclientId");
//                //传送给对应toclientId用户的websocket
//                if (StringUtils.isNotBlank(toclientId) && webSocketMap.containsKey(toclientId)) {
//                    webSocketMap.get(toclientId).sendMessage(jsonObject.toJSONString());
//                } else {
//                    log.error("请求的clientId:" + toclientId + "不在该服务器上");
//                    //否则不在这个服务器上，发送到mysql或者redis
//                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("客户端错误:" + this.clientId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

    /***
     * @Description 给所有客户端发送消息
     * @author shangyue
     * @Date 2021/4/7
     * @param message
     * @return
     */

    public void sendMessageAll(String message) throws IOException {
        for (WebSocketServer item : webSocketMap.values()) {
            log.info("客户消息:" + item.clientId + ",报文:" + message);
            item.session.getAsyncRemote().sendText(message);

        }
    }


    /**
     * 给客户端clientId， 发送消息
     */
    public void sendInfo(String message, @PathParam("clientId") String clientId) throws IOException {
        log.info("发送消息到:" + clientId + "，报文:" + message);
        if (StringUtils.isNotBlank(clientId) && webSocketMap.containsKey(clientId)) {
            webSocketMap.get(clientId).sendMessage(message);
        } else {
            log.error("客户端" + clientId + ",不在线！");

        }
    }
    /*** 功能描述: 设置工作站状态
     * @param clientId used_user_id地址
     * @param type 1在线0离线
     * @Author: lcy
     * @Date: 2021/11/11
     */
    public synchronized void updateStatus(String clientId,String type) {
        //工作站设置在线
        QueryWrapper<ParkWorkStation> wrapper = new QueryWrapper<>();
        wrapper.eq("used_user_id", clientId).orderByDesc("create_time");
        List<ParkWorkStation> list = parkWorkStationMapper.selectList(wrapper);
        if(ObjectUtil.isEmpty(list)){
            log.error("当前used_user_id无对应工作站！");
            return;
        }
        //设置是否在线
        list.get(0).setStatus(type);
        //如果没有上班时间就设置上班时间
        if(ObjectUtil.isEmpty(list.get(0).getUpTime())){
            if(JddConstant.StringNumber.STRING_ONE.equals(type)){
                SimpleDateFormat sim=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                list.get(0).setUpTime(sim.format(new Date()));
            }
        }
        parkWorkStationMapper.updateById(list.get(0));
        log.info("--------"+clientId+"工作站更改为"+(JddConstant.StringNumber.STRING_ONE.equals(type)?"上线":"离线"+"------------"));
    }
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}
